package com.xjh.serverinspect.security.service.impl;

import com.xjh.serverinspect.security.JwtHolder;
import com.xjh.serverinspect.security.model.UsernamePasswordDTO;
import com.xjh.serverinspect.security.service.SecurityService;
import com.xjh.serverinspect.security.service.UserDetailServiceImpl;
import com.xjh.serverinspect.util.ResponseCodeEnum;
import com.xjh.serverinspect.util.ResponseDTO;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 *
 * </p>
 *
 * @author xujinghui
 * @since 2024-12-12
 */
@Service
@Slf4j
public class SecurityServiceImpl implements SecurityService {

    @Resource
    private JwtHolder jwtHolder;

    @Resource
    private PasswordEncoder passwordEncoder;

    @Resource
    private UserDetailServiceImpl userDetailService;

    @Override
    public ResponseDTO login(UsernamePasswordDTO usernamePasswordDTO) {
        UserDetails userDetails = userDetailService.loadUserByUsername(usernamePasswordDTO.getUsername());

        if (passwordEncoder.matches(usernamePasswordDTO.getPassword(), userDetails.getPassword())) {
            Map<String, String> result = new HashMap<>();

            Map<String, Object> claims = new HashMap<>();
            claims.put("username", usernamePasswordDTO.getUsername());

            // access_token
            String accessToken = jwtHolder.createAccessToken(claims);
            result.put("access_token", accessToken);

            // refresh_token
            String refreshToken = jwtHolder.createRefreshToken(claims);
            result.put("refresh_token", refreshToken);

            return ResponseDTO.success(result);
        } else {
            return ResponseDTO.error(ResponseCodeEnum.USERNAME_OR_PASSWORD_ERROR);
        }
    }

    /**
     * 刷新access_token
     *
     * @param refreshToken refresh_token
     * @return ResponseDTO
     */
    @Override
    public ResponseDTO refreshAccessToken(String refreshToken) {
        Map<String, Object> parseToken = jwtHolder.parseToken(refreshToken);
        if ((boolean) parseToken.get("success")) {
            Claims payload = (Claims) parseToken.get("payload");
            Map<String, Object> claims = new HashMap<>();
            claims.put("username", payload.get("username"));
            return ResponseDTO.success(jwtHolder.createAccessToken(claims));
        } else {
            return ResponseDTO.error(ResponseCodeEnum.TOKEN_ERROR, (String) parseToken.get("message"));
        }
    }

    @Override
    public ResponseDTO rsaPublicKey() {
        try {
            InputStream inputStream = new ClassPathResource("RSAPublicKey").getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            return ResponseDTO.success(bufferedReader.readLine());
        } catch (IOException e) {
            log.error("读取公钥失败", e);
            return null;
        }
    }
}
